#include <errno.h>

#include <linux/sched.h>
#include <asm/segment.h>

#define MIN(a, b) (((a) < (b)) ? (a) : (b))

int file_read(struct m_inode *inode, struct file *filp, char *buf, int count)
{
    int left, chars, nr;
    struct buffer_head *bh;

    left = count;
    if (left <= 0) {
        return 0;
    }
    while (left) {
        nr = bmap(inode, (filp->f_pos) / BLOCK_SIZE);
        if (nr) {
            bh = bread(inode->i_dev, nr);
            if (!bh)
                break;
        }
        else
            bh = NULL;
        
        nr = filp->f_pos % BLOCK_SIZE;
        chars = MIN(BLOCK_SIZE - nr, left);
        filp->f_pos += chars;
        left -= chars;
        
        if (bh) {
            char *p = nr + bh->b_data;
            while (chars-- > 0)
                put_fs_byte(*(p++), buf++);
            brelse(bh);
        } else {
            while (chars-- > 0)
                put_fs_byte(0, buf++);
        }
    }
    inode->i_atime = CURRENT_TIME;
    return (count - left) ? (count - left) : -ERROR;
}